<?php

/**
 * @version 1.0
 * @uses lib.class.config
 * @uses lib.exception.xml
 */

class Log {
    private static $target;
    private static $disabled;
    private static $format;
    private static $cfg;
    private static $session = false;
    private static $fname = '';
    private static $logName;
    private static $oTarget;

    public static function target($logName, $format = false) {
        self::$logName = $logName;
        self::$cfg = new Config ( 'log' );
        if (! (self::$cfg->log_write_errors || self::$cfg->log_write_warnings || self::$cfg->log_write_logs))
            return;
        self::$format = ($format) ? $format : self::$cfg->log_format;
        if (self::$target) {
            fclose ( self::$target );
        }
        $fname = self::$cfg->log_directory . '/' . $logName;
        self::$fname = $logName;
        if (!file_exists($fname)) {
            self::make_path($fname);
        }
        if ((@filesize ( $fname ) / 1024 > self::$cfg->log_max_size))
            unlink ( $fname );
        if (self::$disabled = self::$cfg->log_disabled)
            return;
        self::$target = fopen ( $fname, "a" );
        if (self::$target === false)
            throw new Exception ( "Unable to open logfile: $logName" );
    }

    private static function retarget($target = false) {
        if ($target) {
            if (self::$oTarget == self::$logName)
                return;
            self::$oTarget = self::$logName;
            self::target ( $target );
        } else {
            if (self::$oTarget)
                self::target ( self::$oTarget );
            self::$oTarget = NULL;
        }
    }

    public static function targeted() {
        return self::$target;
    }

    public static function fatal($message, $code = 999999) {
        self::retarget ( 'fatal' );
        $msg = $message;
        $message = self::write ( 'ERROR', $message );
        self::retarget ();
        throw new XMLException ( $code, htmlentities ( $msg ) );
    }

    public static function put($message, $target = false) {
        self::retarget ( $target );
        $message = self::write ( 'LOG', $message );
        if (self::$cfg->display_logs)
            echo '<br/>' . htmlentities ( $message ) . '<br/>';
        self::retarget ();
    }

    public static function warning($message, $target = false) {
        self::retarget ( $target );
        $message = self::write ( 'WARNING', $message );
        if (self::$cfg->display_warnings)
            echo '<br/>' . htmlentities ( $message ) . '<br/>';
        self::retarget ();
    }

    private static function write($level, $message) {
        $msg = $message;
        switch ($level) {
            case 'LOG' :
                $p = '>';
                break;
            case 'WARNING' :
                $p = '!';
                break;
            case 'ERROR' :
                $p = 'X';
                break;
        }
        $optName = 'log_write_' . strtolower ( $level ) . 's';
        $message = $p . ' ' . self::format ( $level, $message );
        self::$session .= "<log level='$level' logfile='" . self::$fname . "'>$msg</log>";
        if (! self::$cfg->$optName)
            return $message;
        if (self::$disabled)
            return $message;
        if (! self::$target) {
            self::target ( 'system.log' );
            self::$session .= "<log level='$level' logfile='" . self::$fname . "'>$msg</log>";
            self::fatal ( 'Trying to put message before log opened!' );
        }
        fwrite ( self::$target, $message . "\r\n" );
        return $message;
    }

    private function format($level, $message) {
        $logFormat = self::$format;

        try {
            throw new Exception ( );
        } catch ( Exception $e ) {
            $cb1 = $e->getTrace ();
            $cb [0] = @$cb1 [3] ['class'] . '::' . $cb1 [1] ['function'];
            $cb [1] = @$cb1 [2] ['file'];
            $cb [2] = @$cb1 [2] ['line'];
        }

        $logFormat = str_replace ( '__LEVEL__', $level, $logFormat );
        $logFormat = str_replace ( '__FUNCTION__', $cb [0], $logFormat );
        $logFormat = str_replace ( '__FILE__', $cb [1], $logFormat );
        $logFormat = str_replace ( '__LINE__', $cb [2], $logFormat );
        $logFormat = str_replace ( '__DATE__', date ( self::$cfg->date_format ), $logFormat );
        $logFormat = str_replace ( '__TIME__', date ( self::$cfg->time_format ), $logFormat );
        $message = str_replace ( '__MESSAGE__', $message, $logFormat );

        return $message;
    }

    public static function close() {
        if (self::$disabled)
            return;
        try {
            fclose ( self::$target );
            self::$target = false;
        } catch ( Exception $e ) {
        }
    }

    public static function get_session() {
        return '<logs>' . self::$session . '</logs>';
    }

    public static function setErrorLevel($lvl) {
        if ($lvl >  0) ini_set('display_errors', 'true');
        else ini_set('display_errors', 'false');
        error_reporting($lvl);
    }

    private static function make_path($target) {
        $rp = dirname($target);
        if (!is_dir($rp) && $rp) {
            if (strpos($rp, '/') !== false) $dirs = explode('/', $rp);
            elseif (strpos($rp, '\\') !== false) $dirs = explode('\\', $rp);
            else $dirs = array($rp);
            $dir = '';
            foreach ($dirs as $sd) {
                $dir .= $sd;
                if (!file_exists($dir)) {
                    mkdir($dir);
                }
                $dir .= '/';
            }
        }

    }
}
?>